package qinggui.mlz.module.star.service;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import qinggui.mlz.module.category.entity.Category;
import qinggui.mlz.module.category.service.CategoryService;
import qinggui.mlz.module.star.entity.Star;
import qinggui.mlz.module.star.entity.dto.StarDTO;
import qinggui.mlz.module.star.mapper.StarMapper;
import qinggui.mlz.module.startagrelation.entity.StarTagRelation;
import qinggui.mlz.module.startagrelation.service.StarTagRelationService;
import qinggui.mlz.module.tag.entity.Tag;
import qinggui.mlz.module.tag.service.TagService;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class StarService {
    @Autowired
    private StarMapper starMapper;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private StarTagRelationService starTagRelationService;
    @Autowired
    private TagService tagService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    public Integer insert(Star star) {
        return starMapper.insertStar(star);
    }

    public Integer insertTag(Tag tag) {
        return tagService.insertTag(tag);
    }

    public Integer insertRelation(StarTagRelation starTagRelation) {
        return starTagRelationService.insertStarTagRelation(starTagRelation);
    }

    public Star extractById(Long id) {
        return starMapper.extractById(id);
    }

    public Integer update(Star star) {
        return starMapper.update(star);
    }

    public List<Star> getAll(Integer page, Integer pageSize, String keyword, String ids) {
        return starMapper.getAll((page - 1) * pageSize, pageSize, keyword, ids);
    }

    public Integer delete(Long id, Integer timeStamp) {
        return starMapper.delete(id, timeStamp);
    }

    public Star getById(Long id, Integer timeStamp) {
        return starMapper.getById(id);
    }

    /**
     * 根据关键字获取所有满足条件的数据
     *
     * @param page     页码
     * @param pageSize 展示数
     * @param keyword  关键字
     * @return List<Star>
     */
    public List<Star> getAllLists(Integer page, Integer pageSize, String keyword) {
        if (page == null || pageSize == null) {
            throw new RuntimeException("页码和展示数不能为空");
        }
        String cacheKey = "star_list_key_" + page + "_" + keyword;
        // 先查缓存
        String cacheValue = redisTemplate.opsForValue().get(cacheKey);
        if (cacheValue != null && !cacheValue.isEmpty()) {
            log.info("从缓存中获取第{}页数据，关键字是{}", page, keyword);
            // 将这个数据转成java集合
            return JSON.parseArray(cacheValue, Star.class);
        }
        // 获取分类表中存在这个keyword的数据
        List<Category> categoryList = categoryService.getAllParentCategory(keyword);
        if (categoryList != null && !categoryList.isEmpty()) {
            StringBuilder stringBuilder = new StringBuilder();
            for (Category category : categoryList) {
                // 获取满足数据的id，然后把所有的id拼接起来变成用逗号分割的ids
                stringBuilder.append(category.getId()).append(",");
            }
            // 删除最后一个字符
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            List<Star> all = getAll(page, pageSize, keyword, stringBuilder.toString());
            redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(all), 60 * 60 * 1000, TimeUnit.MILLISECONDS);// 一定要记得json序列化
            log.info("写入缓存成功"+cacheKey);
            return all;
        }
        List<Star> all = getAll(page, pageSize, keyword, null);
        redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(all), 60 * 60 * 1000, TimeUnit.MILLISECONDS);
        log.info("写入缓存成功"+cacheKey);
        return all;
    }

    /**
     * 根据id获取球星信息
     *
     * @param id 主键id
     * @return Star
     */
    public Star getById(Long id) {
        if (id == null || id < 1) {
            throw new RuntimeException("id不能为空或不合法");
        }
        return getById(id, null);
    }


    /**
     * 获取所有球星信息
     *
     * @param page     页码
     * @param pageSize 展示数
     * @return List<Star>
     */
    public List<StarDTO> getAllList(Integer page, Integer pageSize) {
        if (page == null || pageSize == null) {
            throw new RuntimeException("页码和展示数不能为空");
        }
        return starMapper.getAllList((page - 1) * pageSize, pageSize);
    }


    /**
     * 获取所有球星信息总条数
     *
     * @return Integer
     */
    public Integer getAllCount() {
        return starMapper.getAllCount();
    }

    /**
     * 新增/更新球星信息
     *
     * @param id          主键id
     * @param images      球星图片
     * @param categoryId  类目id
     * @param name        球星名称
     * @param age         球星年龄
     * @param gender      球星性别
     * @param workPlace   球星工作地点
     * @param score       球星得分
     * @param pay         球星薪水
     * @param assist      球星助攻
     * @param backboard   球星篮板
     * @param description 球星描述
     * @param tags        标签
     * @return String
     */
    /* 事务属性配置分别为：
     *    1. 默认值，支持当前事务，不存在就新建
     *    2. 使用数据库默认隔离级别（Mysql读已提交）
     *    3. 所有异常都回滚（默认是运行时异常回滚）
     *    4. 默认30秒超时
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class, timeout = 30)
    public String edit(Long id, String images, Long categoryId, String name, Integer age, Integer gender, String workPlace,
                       Float score, Float pay, Float assist, Float backboard, String description, String tags) {
        // 1. 参数校验
        if (id != null && id < 1) {
            throw new RuntimeException("id不合法");
        }
        if (images == null || categoryId == null || name == null || age == null || gender == null
                || workPlace == null || score == null || pay == null || assist == null || backboard == null) {
            throw new RuntimeException("参数不能为空");
        }
        // 2. 类目校验
        Category category = categoryService.getById(categoryId);
        if (category == null) {
            throw new RuntimeException("类目id不存在");
        }
        if (!categoryService.getCategoryByParentId(categoryId).isEmpty()) {
            throw new RuntimeException("类目id不是叶子类目");
        }
        // 3. 球星公共数据准备
        Star star = new Star().setImages(images)
                .setCategoryId(categoryId)
                .setName(name)
                .setAge(age)
                .setGender(gender)
                .setWorkPlace(workPlace)
                .setScore(score)
                .setPay(pay)
                .setAssist(assist)
                .setBackboard(backboard)
                .setDescription(description)
                .setUpdateTime((int) (System.currentTimeMillis() / 1000));
        // 4. 新增逻辑
        if (id == null) {
            Star starEntity = starMapper.getStarByName(name);
            if (starEntity != null) {
                throw new RuntimeException("球星已存在!");
            }
            star.setIsDeleted(0).setCreateTime((int) (System.currentTimeMillis() / 1000));
            insert(star);
            if (tags != null && !tags.trim().isEmpty()) {
                String[] tagsSplit = tags.split("\\s*,\\s*");
                Long starId = star.getId();
                if (starId == null) {
                    throw new RuntimeException("获取新增后球星id失败");
                }
                for (String tag : tagsSplit) {
                    tag = tag.trim();
                    if (tag.isEmpty()) {
                        continue;
                    }
                    Tag tagEntity = tagService.getOneByName(tag);
                    if (tagEntity == null) {
                        // 创建新标签
                        Tag newTag = new Tag().setName(tag)
                                .setCreateTime((int) (System.currentTimeMillis() / 1000))
                                .setUpdateTime((int) (System.currentTimeMillis() / 1000));
                        insertTag(newTag);
                        newTag.setId(newTag.getId());
                        tagEntity = newTag;
                    }
                    if (tagEntity.getId() == null) {
                        throw new RuntimeException("获取标签id失败");
                    }
                    // 检查关系是否已存在
                    List<StarTagRelation> list = starTagRelationService.queryByStarIdAndTagId(starId, tagEntity.getId());
                    if (list.isEmpty()) {
                        // 创建关系
                        StarTagRelation relation = new StarTagRelation()
                                .setStarId(starId)
                                .setTagId(tagEntity.getId())
                                .setCreateTime((int) (System.currentTimeMillis() / 1000))
                                .setUpdateTime((int) (System.currentTimeMillis() / 1000))
                                .setIsDeleted((byte) 0);
                        insertRelation(relation);
                    }
                }
            }
            return "新增成功";
        } else {
            // 更新逻辑
            Star starEntity = starMapper.getStarByName(name);
            if (starEntity == null || !starEntity.getId().equals(id)) {
                throw new RuntimeException("球星不存在!");
            }
            // 更新球星信息
            star.setId(id);
            update(star);
            if (tags != null) {
                String[] tagsSplit = tags.split("\\s*,\\s*");
                for (String tag : tagsSplit) {
                    tag = tag.trim();
                    if (tag.isEmpty()) continue;
                    Tag tagEntity = tagService.getOneByName(tag);
                    if (tagEntity == null) {
                        // 创建新标签并建立关系
                        Tag newTag = new Tag().setName(tag)
                                .setCreateTime((int) (System.currentTimeMillis() / 1000))
                                .setUpdateTime((int) (System.currentTimeMillis() / 1000));
                        insertTag(newTag);
                        StarTagRelation relation = new StarTagRelation()
                                .setStarId(id)
                                .setTagId(newTag.getId())
                                .setCreateTime((int) (System.currentTimeMillis() / 1000))
                                .setUpdateTime((int) (System.currentTimeMillis() / 1000))
                                .setIsDeleted((byte) 0);
                        insertRelation(relation);
                    } else {
                        // 检查关系是否已存在
                        List<StarTagRelation> list = starTagRelationService.queryByStarIdAndTagId(id, tagEntity.getId());
                        if (list.isEmpty()) {
                            // 创建关系
                            StarTagRelation relation = new StarTagRelation()
                                    .setStarId(id)
                                    .setTagId(tagEntity.getId())
                                    .setCreateTime((int) (System.currentTimeMillis() / 1000))
                                    .setUpdateTime((int) (System.currentTimeMillis() / 1000))
                                    .setIsDeleted((byte) 0);
                            insertRelation(relation);
                        }
                    }
                }
            }
            return "更新成功";
        }
    }

    /**
     * 删除球星
     *
     * @param id 主键id
     * @return String
     */
    public String delete(Long id) {
        if (id == null || id < 1) {
            throw new RuntimeException("id不能为空或不合法");
        }
        int timeStamp = (int) (System.currentTimeMillis() / 1000);
        return delete(id, timeStamp) == 1 ? "成功" : "失败";
    }
}


